﻿using System;
using WiMo.Games.Menus;
using WiMo.Games.Inputs;
using WiMo.Games.Drawables;

namespace WiMo.Games.StandardMenus
{
    public class MenuComponent : IMenuComponent
    {
        private const int INT_ROW_HEIGHT = 36;
        private const int INT_SIDE_MARGINS = 25;
        private const int INT_HEADER_HEIGHT = 25;

        private int _selectedMenuIndex;
        public bool IsVisible { get; set; }
        public string Title { get; set; }
        public Color FrameColor { get; set; }
        public Color TitleColor { get; set; }
        public Color BackgroundColor { get; set; }
        
        public Color DisabledMenuItemColor { get; set; }
        
        public Color SelectedItemColor { get; set; }
        public Color SelectedItemBorderColor { get; set; }
        public Color SelectedItemBackground { get; set; }

        public ISpriteFont TitleFont { get; set; }

        private ISpriteFont _menuItemFont;
        public ISpriteFont MenuItemFont
        {
            get{return _menuItemFont;}
            set
            {
                _menuItemFont = value;
                foreach (var menu in MenuItems)
                    menu.TextSprite.Font = MenuItemFont;
            }
        }

        private Color _menuItemColor;
        public Color MenuItemColor
        {
            get
            {
                return _menuItemColor;
            }
            set
            {
                _menuItemColor = value;
                foreach (var menu in MenuItems)
                    menu.TextSprite.ForeColor = MenuItemColor;
            }
        }

        public System.Collections.Generic.List<IMenu> MenuItems { get; set; }

        private ISpriteText _title;
        private ISpriteShape _menuRect;
        private ISpriteShape _selectedItemRect;

        public MenuComponent(IGameEngine engine)
        {
            MenuItems = new System.Collections.Generic.List<IMenu>();

            _selectedMenuIndex = 0;
            Engine = engine;
            TitleColor = Color.Black;
            MenuItemColor = Color.Black;
            FrameColor = Color.Silver;
            BackgroundColor = new Color(Color.LightGray, 0xb0);
            SelectedItemBorderColor = Color.Silver;
            SelectedItemBackground = Color.LightBlue;
            SelectedItemColor = Color.Black;

            _menuRect = engine.AssetFactory.CreateRectangle();
            _selectedItemRect = engine.AssetFactory.CreateRectangle();
            _title = engine.AssetFactory.CreateText();

            Title = string.Empty;
        }
        public IInputManager InputManager { get; set; }

        public event EventHandler<SelectedMenuEventArgs> MenuSelected;

        public void Reset()
        {
            _selectedMenuIndex = 0;
        }

        public void Show()
        {
            IsVisible = true;
        }

        public void Hide()
        {
            IsVisible = false;
        }

        public void Show(Direction direction)
        {
            IsVisible = true;
        }

        public void Hide(Direction direction)
        {
            IsVisible = false;
        }

        public void Up()
        {
            if (_selectedMenuIndex == 0)
                _selectedMenuIndex = MenuItems.Count - 1;
            else
                _selectedMenuIndex--;
        }

        public void Down()
        {
            if (_selectedMenuIndex == MenuItems.Count - 1)
                _selectedMenuIndex = 0;
            else
                _selectedMenuIndex++;
        }

        private void Select(IMenu menu)
        {
            if (menu.MenuComponent != null)
            {
                this.Hide();
                menu.MenuComponent.Reset();
                menu.MenuComponent.Show();
            }
            else
            {
                _selectedMenuIndex = menu.MenuIndex;
                if (MenuSelected != null)
                    MenuSelected(this, new SelectedMenuEventArgs(menu));
            }
        }

        public void Select()
        {
            Select(MenuItems[_selectedMenuIndex]);
        }

        public void SelectByIndex(int menuIndex)
        {
            throw new NotImplementedException();
        }

        public void SelectByMenuId(int menuId)
        {
            throw new NotImplementedException();
        }

        public IGameEngine Engine { get; set; }
        public int DrawOrder { get; set; }
        public IDisplay Display { get; set; }

        public IMenu AddMenu(string text, int menuId)
        {
            var menu = new Menu(Engine) { Text = text, MenuId = menuId, MenuIndex = MenuItems.Count };
            MenuItems.Add(menu);
            menu.TextSprite.Font = MenuItemFont;
            menu.TextSprite.ForeColor = MenuItemColor;

            return menu;
        }

        public IMenu AddMenu(string text, IMenuComponent menuComponent)
        {
            var menu = new Menu(Engine) { Text = text, MenuComponent = menuComponent, MenuIndex = MenuItems.Count };
            MenuItems.Add(menu);
            menu.TextSprite.Font = MenuItemFont;
            menu.TextSprite.ForeColor = MenuItemColor;

            return menu;
        }

        IInputManager _lastState = null;

        public void LoadContent(IContentManager content)
        {
            TitleFont = content.GetFont("WiMoGamesMenuTitle"); 
            TitleFont.Size = 12.0f;
            TitleFont.Bold = true;
            TitleFont.Name = "Tahoma";

            MenuItemFont = content.GetFont("WiMoGamesMenuItem");
            MenuItemFont.Size = 10.0f;
            MenuItemFont.Bold = true;
            MenuItemFont.Name = "Tahoma";

            foreach (var menu in MenuItems)
            {
                menu.TextSprite.Font = MenuItemFont;
                menu.TextSprite.ForeColor = MenuItemColor;
            }
        }

        public virtual void Initialize(){ }

        public void Update(GameTime gameTime)
        {
            if (!this.IsVisible)
                return;

            if (_lastState == null)
                _lastState = Engine.InputManager.GetKeysState();

            if (Engine.InputManager.IsPressed(_lastState, Keys.Up, 250, false))
                Up();

            if (Engine.InputManager.IsPressed(_lastState, Keys.Down, 250, false))
                Down();

            if (Engine.InputManager.WasPressed(_lastState, Keys.Return))
                Select();

            var panelHeight = MenuItems.Count * INT_ROW_HEIGHT;
            var panelWidth = Engine.Display.TargetSize.Width - INT_SIDE_MARGINS * 2;

            if (Title != string.Empty)
                panelHeight += INT_HEADER_HEIGHT;

            var top = new Location(INT_SIDE_MARGINS, (Engine.Display.TargetSize.Height - panelHeight) / 2);
            top += new Vector2(0, INT_HEADER_HEIGHT);

            foreach(var menu in MenuItems)
            {
                var menuRect = new Rectangle(top.X, top.Y, panelWidth, INT_ROW_HEIGHT);

                if (Engine.InputManager.WasScreenTouched(_lastState, menuRect))
                {
                    Select(menu);
                    _lastState = Engine.InputManager.GetKeysState();
                    return;
                }
                top += new Vector2(0, INT_ROW_HEIGHT);
            }

            _lastState = Engine.InputManager.GetKeysState();
        }

        public void Draw(GameTime gameTime)
        {
            if (!IsVisible)
                return;

            var panelHeight = MenuItems.Count * INT_ROW_HEIGHT;
            var panelWidth = Engine.Display.TargetSize.Width - INT_SIDE_MARGINS * 2;

            if (Title != string.Empty)
                panelHeight += INT_HEADER_HEIGHT;

            var top = new Location(INT_SIDE_MARGINS, (Engine.Display.TargetSize.Height - panelHeight) / 2);

            _menuRect.Position = new PointF(top.X, top.Y);
            _menuRect.Size = new Size(panelWidth, panelHeight);
            _menuRect.FillColor = BackgroundColor;
            _menuRect.BorderColor = FrameColor;
            _menuRect.BorderWidth = 4;
            _menuRect.BorderRadius = 20;
            _menuRect.Origin = Origin.TopLeft;

            Engine.Display.Add(_menuRect);
            
            if (Title != string.Empty)
            {
                _title.Font = TitleFont;
                _title.Text = Title;
                _title.ForeColor = TitleColor;
                _title.Position = new PointF(top.X + 3, top.Y + 3);
                _title.Origin = Origin.TopLeft;
                top += new Vector2(0, INT_HEADER_HEIGHT);
                Engine.Display.Add(_title);
            }

            foreach (Menu menu in MenuItems )
            {
                menu.TextSprite.Position = new PointF(top.X + 3, top.Y + 3);
                menu.TextSprite.Font = MenuItemFont;
                //menu.TextSprite.Size = new Size(panelWidth, INT_ROW_HEIGHT);

                if (_selectedMenuIndex == menu.MenuIndex)
                {
                    _selectedItemRect.Origin = Origin.TopLeft;
                    _selectedItemRect.Position = new PointF(top.X + 1, top.Y + 2);
                    _selectedItemRect.Size = new Size(panelWidth - 2, INT_ROW_HEIGHT - 2);
                    _selectedItemRect.FillColor = SelectedItemBackground;
                    _selectedItemRect.BorderColor = SelectedItemBorderColor;
                    _selectedItemRect.BorderWidth = 2;
                    menu.TextSprite.BackgroundColor = SelectedItemBackground;

                    Engine.Display.Add(_selectedItemRect);
                }
                else
                    menu.TextSprite.BackgroundColor = BackgroundColor;

                Engine.Display.Add(menu.TextSprite);

                menu.Render(Engine.Display);

                top += new Vector2(0, INT_ROW_HEIGHT);
            }
        }

        public void Dispose()
        {
            MenuItemFont.Dispose();
            TitleFont.Dispose();
        }
    }
}
